package org.elanfox.intellicommunity.intellicommunityadmin.config;

import org.elanfox.intellicommunity.biz.service.core.auth.SystemService;
import org.elanfox.intellicommunity.intellicommunityadmin.base.security.SmAuthenticationProcessingFilter;
import org.elanfox.intellicommunity.intellicommunityadmin.base.security.SmAuthenticationProvider;
import org.elanfox.intellicommunity.intellicommunityadmin.base.security.SmAuthenticationSuccessHandler;
import org.elanfox.intellicommunity.intellicommunityadmin.base.security.SmSecurityFailureHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.Collections;

/**
 * @author allan
 * @date 2019-10-12
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    public static final String LOGIN_URL = "/login";
    public static final String LOGIN_SUCCESS_URL = "/home";
    public static final String LOGIN_FAILED_URL = "/loginFailed";
    public static final String LOGOUT_SUCCESS_URL = "/";

    private static String[] STATIC_RESOURCE_PATH = {
            "classpath:/resource/**",
            "/resource/**",
            "/verifyCode/verifyImage",
            "/api/**",
            "/verifyCode",
    };


    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers(STATIC_RESOURCE_PATH);
    }

    @Autowired
    private SystemService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers().frameOptions().sameOrigin()
                .and()
                .addFilter(smAuthenticationProcessingFilter())
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .formLogin()
                .loginPage(LOGIN_URL)
                .failureUrl(LOGIN_FAILED_URL)
                .permitAll()
                .and()
                .logout()
                .logoutSuccessUrl(LOGOUT_SUCCESS_URL);
    }

    /**
     * 定义一个适用于本项目的权限校验过滤器
     *
     * @return
     */
    private SmAuthenticationProcessingFilter smAuthenticationProcessingFilter() {
        SmAuthenticationProvider authenticationProvider = new SmAuthenticationProvider();
        authenticationProvider.setPasswordEncoder(passwordEncoder);
        authenticationProvider.setSystemService(userDetailsService);

        //权限校验管理器，当然可以包含多个提供者
        AuthenticationManager authenticationManager = new ProviderManager(
                Collections.singletonList(authenticationProvider)
        );
        SmAuthenticationProcessingFilter authenticationProcessingFilter = new SmAuthenticationProcessingFilter();
        authenticationProcessingFilter.setAuthenticationManager(authenticationManager);
        authenticationProcessingFilter.setAuthenticationSuccessHandler(new SmAuthenticationSuccessHandler());
        authenticationProcessingFilter.setAuthenticationFailureHandler(new SmSecurityFailureHandler(LOGIN_FAILED_URL));
        return authenticationProcessingFilter;
    }
}
